<!doctype html>



  


<html class="theme-next mist use-motion" lang="zh-Hans">
<head>
  <meta charset="UTF-8"/>
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1"/>



<meta http-equiv="Cache-Control" content="no-transform" />
<meta http-equiv="Cache-Control" content="no-siteapp" />












  
  
  <link href="/lib/fancybox/source/jquery.fancybox.css?v=2.1.5" rel="stylesheet" type="text/css" />




  
  
  
  

  
    
    
  

  

  

  

  

  
    
    
    <link href="//fonts.googleapis.com/css?family=Lato:300,300italic,400,400italic,700,700italic&subset=latin,latin-ext" rel="stylesheet" type="text/css">
  






<link href="/lib/font-awesome/css/font-awesome.min.css?v=4.6.2" rel="stylesheet" type="text/css" />

<link href="/css/main.css?v=5.1.0" rel="stylesheet" type="text/css" />


  <meta name="keywords" content="jenkins,ansible,playbook," />








  <link rel="shortcut icon" type="image/x-icon" href="/favicon.ico?v=5.1.0" />






<meta name="description" content="前文回顾前文我们讲述了用于IT自动化过程中的持续测试环节和工具。本文将对IT自动化过程中的另一个重要环节——系统部署 所需要的自动化工具进行详细介绍。">
<meta property="og:type" content="article">
<meta property="og:title" content="IT自动化(11)——持续部署的支撑工具Ansible">
<meta property="og:url" content="http://chrisrc.me/2015/09/23/autoit-ansible/index.html">
<meta property="og:site_name" content="山中，山外与俯瞰">
<meta property="og:description" content="前文回顾前文我们讲述了用于IT自动化过程中的持续测试环节和工具。本文将对IT自动化过程中的另一个重要环节——系统部署 所需要的自动化工具进行详细介绍。">
<meta property="og:image" content="http://chrisrc.me/images/autoit_ansible_tools.png">
<meta property="og:image" content="http://chrisrc.me/images/autoit_ansible_arch.png">
<meta property="og:updated_time" content="2016-12-17T07:29:29.000Z">
<meta name="twitter:card" content="summary">
<meta name="twitter:title" content="IT自动化(11)——持续部署的支撑工具Ansible">
<meta name="twitter:description" content="前文回顾前文我们讲述了用于IT自动化过程中的持续测试环节和工具。本文将对IT自动化过程中的另一个重要环节——系统部署 所需要的自动化工具进行详细介绍。">
<meta name="twitter:image" content="http://chrisrc.me/images/autoit_ansible_tools.png">



<script type="text/javascript" id="hexo.configurations">
  var NexT = window.NexT || {};
  var CONFIG = {
    root: '/',
    scheme: 'Mist',
    sidebar: {"position":"left","display":"post"},
    fancybox: true,
    motion: true,
    duoshuo: {
      userId: '0',
      author: '博主'
    },
    algolia: {
      applicationID: '',
      apiKey: '',
      indexName: '',
      hits: {"per_page":10},
      labels: {"input_placeholder":"Search for Posts","hits_empty":"We didn't find any results for the search: ${query}","hits_stats":"${hits} results found in ${time} ms"}
    }
  };
</script>



  <link rel="canonical" href="http://chrisrc.me/2015/09/23/autoit-ansible/"/>





  <title> IT自动化(11)——持续部署的支撑工具Ansible | 山中，山外与俯瞰 </title>
</head>

<body itemscope itemtype="http://schema.org/WebPage" lang="zh-Hans">

  










  
  
    
  

  <div class="container one-collumn sidebar-position-left page-post-detail ">
    <div class="headband"></div>

    <header id="header" class="header" itemscope itemtype="http://schema.org/WPHeader">
      <div class="header-inner"><div class="site-meta ">
  

  <div class="custom-logo-site-title">
    <a href="/"  class="brand" rel="start">
      <span class="logo-line-before"><i></i></span>
      <span class="site-title">山中，山外与俯瞰</span>
      <span class="logo-line-after"><i></i></span>
    </a>
  </div>
  <p class="site-subtitle">一次永不停止的探索之旅</p>
</div>

<div class="site-nav-toggle">
  <button>
    <span class="btn-bar"></span>
    <span class="btn-bar"></span>
    <span class="btn-bar"></span>
  </button>
</div>

<nav class="site-nav">
  

  
    <ul id="menu" class="menu">
      
        
        <li class="menu-item menu-item-home">
          <a href="/" rel="section">
            
              <i class="menu-item-icon fa fa-fw fa-home"></i> <br />
            
            首页
          </a>
        </li>
      
        
        <li class="menu-item menu-item-dcos">
          <a href="/dcos" rel="section">
            
              <i class="menu-item-icon fa fa-fw fa-book"></i> <br />
            
            DC/OS
          </a>
        </li>
      
        
        <li class="menu-item menu-item-categories">
          <a href="/categories" rel="section">
            
              <i class="menu-item-icon fa fa-fw fa-th"></i> <br />
            
            分类
          </a>
        </li>
      
        
        <li class="menu-item menu-item-about">
          <a href="/about" rel="section">
            
              <i class="menu-item-icon fa fa-fw fa-user"></i> <br />
            
            关于
          </a>
        </li>
      
        
        <li class="menu-item menu-item-archives">
          <a href="/archives" rel="section">
            
              <i class="menu-item-icon fa fa-fw fa-archive"></i> <br />
            
            归档
          </a>
        </li>
      
        
        <li class="menu-item menu-item-tags">
          <a href="/tags" rel="section">
            
              <i class="menu-item-icon fa fa-fw fa-tags"></i> <br />
            
            标签
          </a>
        </li>
      

      
        <li class="menu-item menu-item-search">
          
            <a href="javascript:;" class="st-search-show-outputs">
          
            
              <i class="menu-item-icon fa fa-search fa-fw"></i> <br />
            
            搜索
          </a>
        </li>
      
    </ul>
  

  
    <div class="site-search">
      
  <form class="site-search-form">
  <input type="text" id="st-search-input" class="st-search-input st-default-search-input" />
</form>

<script type="text/javascript">
  (function(w,d,t,u,n,s,e){w['SwiftypeObject']=n;w[n]=w[n]||function(){
    (w[n].q=w[n].q||[]).push(arguments);};s=d.createElement(t);
    e=d.getElementsByTagName(t)[0];s.async=1;s.src=u;e.parentNode.insertBefore(s,e);
  })(window,document,'script','//s.swiftypecdn.com/install/v2/st.js','_st');

  _st('install', 'R9GcmhBwxpsAGLNCsquZ','2.0.0');
</script>



    </div>
  
</nav>



 </div>
    </header>

    <main id="main" class="main">
      <div class="main-inner">
        <div class="content-wrap">
          <div id="content" class="content">
            

  <div id="posts" class="posts-expand">
    

  

  
  
  

  <article class="post post-type-normal " itemscope itemtype="http://schema.org/Article">
  <link itemprop="mainEntityOfPage" href="http://chrisrc.me/2015/09/23/autoit-ansible/">

  <span style="display:none" itemprop="author" itemscope itemtype="http://schema.org/Person">
    <meta itemprop="name" content="chrisrc">
    <meta itemprop="description" content="">
    <meta itemprop="image" content="/images/avatar.gif">
  </span>

  <span style="display:none" itemprop="publisher" itemscope itemtype="http://schema.org/Organization">
    <meta itemprop="name" content="山中，山外与俯瞰">
    <span style="display:none" itemprop="logo" itemscope itemtype="http://schema.org/ImageObject">
      <img style="display:none;" itemprop="url image" alt="山中，山外与俯瞰" src="">
    </span>
  </span>

    
      <header class="post-header">

        
        
          <h1 class="post-title" itemprop="name headline">
            
            
              
                IT自动化(11)——持续部署的支撑工具Ansible
              
            
          </h1>
        

        <div class="post-meta">
          <span class="post-time">
            
              <span class="post-meta-item-icon">
                <i class="fa fa-calendar-o"></i>
              </span>
              <span class="post-meta-item-text">发表于</span>
              <time title="Post created" itemprop="dateCreated datePublished" datetime="2015-09-23T20:16:24+08:00">
                2015-09-23
              </time>
            

            

            
          </span>

          
            <span class="post-category" >
              <span class="post-meta-divider">|</span>
              <span class="post-meta-item-icon">
                <i class="fa fa-folder-o"></i>
              </span>
              <span class="post-meta-item-text">分类于</span>
              
                <span itemprop="about" itemscope itemtype="http://schema.org/Thing">
                  <a href="/categories/IT自动化/" itemprop="url" rel="index">
                    <span itemprop="name">IT自动化</span>
                  </a>
                </span>

                
                
              
            </span>
          

          
            
              <span class="post-comments-count">
                <span class="post-meta-divider">|</span>
                <a href="/2015/09/23/autoit-ansible/#comments" itemprop="discussionUrl">
                  <span class="post-comments-count ds-thread-count" data-thread-key="2015/09/23/autoit-ansible/" itemprop="commentCount"></span>
                </a>
              </span>
            
          

          

          
          

          

          

        </div>
      </header>
    


    <div class="post-body" itemprop="articleBody">

      
      

      
        <h2 id="前文回顾"><a href="#前文回顾" class="headerlink" title="前文回顾"></a>前文回顾</h2><p><a href="">前文</a>我们讲述了用于IT自动化过程中的持续测试环节和工具。本文将对IT自动化过程中的另一个重要环节——<strong>系统部署</strong> 所需要的自动化工具<br>进行详细介绍。</p>
<a id="more"></a>
<h2 id="Ansible简介"><a href="#Ansible简介" class="headerlink" title="Ansible简介"></a>Ansible简介</h2><p><a href="http://www.ansible.com" target="_blank" rel="external">Ansible</a>是一款轻量级的功能强大的自动化部署和配置管理工具。之所以如此推荐，是因为Ansible的应用起点底，见效快，适应范围广，从简单的小项目<br>到大型的大规模集群，都可以在生产环境中得到实际应用。</p>
<p>Ansible采用Python实现，其功能建立在SSH之上，采用YAML作为部署脚本。Python和SSH环境是当前Linux服务器系统的必备条件，因此在服务器上<br>运行Ansible非常简单。Ansible 支持对集群的小部分机器批量操作，然后逐步完成整个集群的操作。这对于需要机器重启的场景就非常实用。<br>通过Vagrant本地虚拟机，可以方便的模拟线上环境调试。Ansible也支持多个不同的云服务。</p>
<h2 id="Ansible的安装"><a href="#Ansible的安装" class="headerlink" title="Ansible的安装"></a>Ansible的安装</h2><h3 id="依赖"><a href="#依赖" class="headerlink" title="依赖"></a>依赖</h3><ul>
<li>Python 2.6 或更高版本</li>
<li>Paramiko（Python的SSH模块）</li>
<li>PyYAML（Python的YAML解析器）</li>
<li>Jinja2（Python的模板引擎）</li>
</ul>
<h3 id="安装"><a href="#安装" class="headerlink" title="安装"></a>安装</h3><ul>
<li><p>Ubuntu/Debian系列：</p>
<blockquote>
<p><code>sudo apt-get install ansible</code></p>
</blockquote>
</li>
<li><p>Fedora/CentOS系列：</p>
<blockquote>
<p><code>sudo yum install ansible</code></p>
</blockquote>
</li>
<li><p>通过<code>pip</code>安装ansible：</p>
<blockquote>
<p><code>pip install ansible</code></p>
</blockquote>
</li>
</ul>
<h3 id="本机环境的配置"><a href="#本机环境的配置" class="headerlink" title="本机环境的配置"></a>本机环境的配置</h3><p><strong>说明：下面配置，将本机作为Ansible的目标主机。</strong>  </p>
<p>在<code>/etc/ansible</code>目录下有<code>ansible.cfg</code> 和 <code>hosts</code> 两个Ansible的全局配置文件。</p>
<p>修改<code>/etc/ansible/hosts</code>文件，将所有的示例地址都注释掉，添加本机地址<code>127.0.0.1</code>，保存后执行下述命令：</p>
<blockquote>
<p><code>ansible all -m ping</code></p>
</blockquote>
<p>如果出现异常：<br><figure class="highlight plain"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div></pre></td><td class="code"><pre><div class="line">127.0.0.1 | FAILED =&gt; SSH Error: Permission denied (publickey,password).</div><div class="line">    while connecting to 127.0.0.1:22</div></pre></td></tr></table></figure></p>
<p>按下面的步骤解决（如果当前没有<code>.ssh</code>目录，先用<code>ssh-keygen</code>生成本用户的公私钥）：</p>
<p><code>cat ~/.ssh/id_rsa.pub | ssh chrisrc@127.0.0.1 &quot;mkdir -p ~/.ssh &amp;&amp; cat &gt;&gt; ~/.ssh/authorized_keys&quot;</code></p>
<p>以<code>root</code>用户权限执行下述命令：<br><figure class="highlight plain"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div></pre></td><td class="code"><pre><div class="line">sudo mkdir /etc/ssh/chrisrc</div><div class="line">sudo cp /home/chrisrc/.ssh/authorized_keys /etc/ssh/chrisrc/</div><div class="line">sudo chown -R chrisrc:chrisrc /etc/ssh/chrisrc</div><div class="line">sudo chmod 755 /etc/ssh/chrisrc</div><div class="line">sudo chmod 644 /etc/ssh/chrisrc/authorized_keys</div><div class="line">sudo vim /etc/ssh/sshd_config</div><div class="line">    #RSAAuthentication yes</div><div class="line">    #PubkeyAuthentication yes</div><div class="line">    # Changed .ssh/authorized_keys to /etc/ssh/chrisrc/authorized_keys &lt;&lt;&lt;&lt;&lt;&lt;&lt;</div><div class="line">    AuthorizedKeysFile      /etc/ssh/chrisrc/authorized_keys</div><div class="line">    #AuthorizedKeysCommand none</div><div class="line">    #AuthorizedKeysCommandRunAs nobody</div></pre></td></tr></table></figure></p>
<p>重试命令<code>ansible all -m ping</code>，得到结果：<br><figure class="highlight plain"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div></pre></td><td class="code"><pre><div class="line">127.0.0.1 | success &gt;&gt; &#123;</div><div class="line">    &quot;changed&quot;: false,</div><div class="line">    &quot;ping&quot;: &quot;pong&quot;</div><div class="line">&#125;</div></pre></td></tr></table></figure></p>
<p>说明本机Ansible作为目标主机运行正常。</p>
<h2 id="Ansible常用命令简介"><a href="#Ansible常用命令简介" class="headerlink" title="Ansible常用命令简介"></a>Ansible常用命令简介</h2><p>Ansible提供的命令行指令如下：  </p>
<ul>
<li>ansible: 简单命令行指令</li>
<li>ansible-doc: 查看module(yum,file,command,…）的帮助文档</li>
<li>ansible-playbook: 运行playbook部署脚本</li>
<li>ansible-galaxy：安装第三方module/plugin</li>
<li>ansible-vault： 加密配置文件</li>
<li>ansible-pull: 以PULL模式部署</li>
</ul>
<h3 id="ansible-命令"><a href="#ansible-命令" class="headerlink" title="ansible 命令"></a>ansible 命令</h3><p><code>ansible 主机 -m &quot;模块名称&quot; -a &quot;模块参数&quot;  -v（-vv, -vvv，-vvvv）</code></p>
<blockquote>
<p>ansible 127.0.0.1 -m “command” -a “ls /opt”<br>ansible 127.0.0.1 -a “ls /opt”</p>
</blockquote>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div></pre></td><td class="code"><pre><div class="line">~  ansible 127.0.0.1 -m &quot;command&quot; -a &quot;ls /opt&quot;</div><div class="line">127.0.0.1 | success | rc=0 &gt;&gt;</div><div class="line">...</div><div class="line">gitlab</div><div class="line">google</div><div class="line">kingsoft</div><div class="line">sublime_text</div><div class="line">vagrant</div></pre></td></tr></table></figure>
<h3 id="ansible-doc-命令"><a href="#ansible-doc-命令" class="headerlink" title="ansible-doc 命令"></a>ansible-doc 命令</h3><p><code>ansible-doc -l | grep file</code><br><code>ansible-doc file</code></p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div><div class="line">13</div><div class="line">14</div><div class="line">15</div><div class="line">16</div><div class="line">17</div><div class="line">18</div><div class="line">19</div><div class="line">20</div><div class="line">21</div></pre></td><td class="code"><pre><div class="line">acl                           Sets and retrieves file ACL information.</div><div class="line">assemble                      Assembles a configuration file from fragments</div><div class="line">at                            Schedule the execution of a command or script file via the at ...</div><div class="line">bzr                           Deploy software (or files) from bzr branches</div><div class="line">copy                          Copies files to remote locations.</div><div class="line">fetch                         Fetches a file from remote nodes</div><div class="line">file                          Sets attributes of files</div><div class="line">filesystem                    Makes file system on block device</div><div class="line">get_url                       Downloads files from HTTP, HTTPS, or FTP to node</div><div class="line">git                           Deploy software (or files) from git checkouts</div><div class="line">htpasswd                      manage user files for basic authentication</div><div class="line">include_vars                  Load variables from files, dynamically within a task.</div><div class="line">ini_file                      Tweak settings in INI files</div><div class="line">known_hosts                   Add or remove a host from the `known_hosts&apos; file</div><div class="line">lineinfile                    Ensure a particular line is in a file, or replace an existing ...</div><div class="line">patch                         Apply patch files using the GNU patch tool.</div><div class="line">rax_files                     Manipulate Rackspace Cloud Files Containers</div><div class="line">rax_files_objects             Upload, download, and delete objects in Rackspace Cloud Files</div><div class="line">replace                       Replace all instances of a particular string in a file using a...</div><div class="line">s3                            S3 module putting a file into S3.</div><div class="line">......</div></pre></td></tr></table></figure>
<h3 id="ansible-playbook-命令"><a href="#ansible-playbook-命令" class="headerlink" title="ansible-playbook 命令"></a>ansible-playbook 命令</h3><p><code>ansible-playbook -i [主机配置清单] [主Playbook(site.yml)] --extra-vars &quot;JAVA_HOME=...&quot; -vvvv</code></p>
<h2 id="自动化部署工具简单比较"><a href="#自动化部署工具简单比较" class="headerlink" title="自动化部署工具简单比较"></a>自动化部署工具简单比较</h2><p><img src="/images/autoit_ansible_tools.png" alt="Auto Deploy Tools"></p>
<p>如上图所示，当前主流的自动化部署工具有：Chef, Puppet, Ansible, SaltStack 和 Fabric。这些工具的优缺点简单列举如下：</p>
<ul>
<li><p>Ansible （YAML/SSH）  </p>
<ul>
<li><p>优点：  </p>
<ul>
<li>基于SSH，不需要在远端部署节点上安装任何代理</li>
<li>使用YAML，学习曲线平滑</li>
<li>部署脚本使用Playbook，结构简单，清晰</li>
<li>分级变量定义控制作用范围，支持动态注册变量</li>
<li>比其他工具更精简的代码库</li>
<li>支持推送和PULL模式，可用于持续部署</li>
</ul>
</li>
<li><p>缺点：  </p>
<ul>
<li>相比于使用其他语言的工具，功能偏弱</li>
<li>使用自己的DSL，在熟悉前需要频繁查阅文档</li>
<li>变量传递，导致脚本复杂</li>
<li>输入、输出和配置不具有一致性</li>
</ul>
</li>
</ul>
</li>
</ul>
<ul>
<li><p>Chef （Ruby）  </p>
<ul>
<li><p>优点：  </p>
<ul>
<li>丰富的模块和配置集</li>
<li>代码驱动</li>
<li>以Git为中心的版本控制</li>
</ul>
</li>
<li><p>缺点：  </p>
<ul>
<li>学习曲线陡峭，需要熟悉ruby及过程编程</li>
<li>实际部署会导致大量的编程维护</li>
<li>不支持push模式</li>
</ul>
</li>
</ul>
</li>
<li><p>Fabric （Python）  </p>
<ul>
<li>优点：  <ul>
<li>可以部署任何语言的应用</li>
<li>相比其它工具，简单易用</li>
<li>与SSH深度集成</li>
</ul>
</li>
<li>缺点：  <ul>
<li>存在单点故障问题</li>
<li>采用推送模型，相比于Ansible，不太适合持续部署</li>
<li>仍需要Python语言环境</li>
</ul>
</li>
</ul>
</li>
</ul>
<ul>
<li><p>Puppet （Ruby）  </p>
<ul>
<li><p>优点：  </p>
<ul>
<li>可以通过Puppet Labs获得良好的社区支持</li>
<li>具有成熟的接口，支持绝大部分操作系统</li>
<li>简单的安装和初始化配置</li>
<li>完整的Web UI管理</li>
<li>强大的报表能力</li>
</ul>
</li>
<li><p>缺点：  </p>
<ul>
<li>对于比较高级的任务，需要使用CLI环境，必须熟悉Ruby</li>
<li>直接基于纯粹Ruby的配置在减少，多少基于自定义DSL</li>
<li>由于DSL不注重简洁，会导致大量臃肿的部署代码</li>
</ul>
</li>
</ul>
</li>
<li><p>Saltstack （Python）  </p>
<ul>
<li><p>优点：  </p>
<ul>
<li>完成安装后就可以直接组织和使用</li>
<li>其DSL有丰富的特性，不需要罗辑和状态</li>
<li>输入、输出和配置具有一致性（都是采用YAML）</li>
<li>通过Salt可以跟踪部署的执行情况</li>
<li>强大的社区支持</li>
</ul>
</li>
<li><p>缺点：  </p>
<ul>
<li>对新手来说难于安装和使用</li>
<li>对入门级层次来说，文档难于理解</li>
<li>对于非Linux系统支持差</li>
</ul>
</li>
</ul>
</li>
</ul>
<p><strong>提示：</strong> 本节内容来自<a href="http://blog.takipi.com/deployment-management-tools-chef-vs-puppet-vs-ansible-vs-saltstack-vs-fabric/" target="_blank" rel="external">Deployment Management Tools: Chef vs. Puppet vs. Ansible vs. SaltStack vs. Fabric</a></p>
<h2 id="Ansible的功能"><a href="#Ansible的功能" class="headerlink" title="Ansible的功能"></a>Ansible的功能</h2><h3 id="工作机制"><a href="#工作机制" class="headerlink" title="工作机制"></a>工作机制</h3><p><img src="/images/autoit_ansible_arch.png" alt="Ansible Arch"></p>
<p>如上图（<a href="http://terry.im/wiki/terry/Ansible.html" target="_blank" rel="external">图片来源</a>）所示，Ansible通过一个核心和如下构件实现部署与配置：  </p>
<ul>
<li><em>Modules</em><br>包括 Ansible 自带的核心模块及自定义模块，提供实现部署所需要的一系列处理单元。</li>
<li><em>Plugins</em><br>完成模块功能的补充，包括连接插件、邮件插件等。</li>
<li><em>Playbooks</em><br>定义 Ansible 多任务配置文件，描述实现一个具体部署的详细动作配置，由Ansible 自动执行。</li>
<li><em>Inventory</em><br>定义 Ansible 管理主机的清单。</li>
</ul>
<h3 id="部署中的基本概念"><a href="#部署中的基本概念" class="headerlink" title="部署中的基本概念"></a>部署中的基本概念</h3><p>首先我们理解一下Ansible的应用概念。简单来说，Ansible通过<em>YAML格式</em>的<em>Playbook脚本</em>定义需要部署到<em>一组目标主机</em>上的<em>系统构件</em>及<br>运行这些构件所需要的<em>基础软件环境</em>。<br>举例来说，当我们需要部署一个Web应用到服务器时，我们需要部署JDK运行环境，部署Tomcat，部署我们的Web应用，<br>对Web应用的配置参数（数据库IP等）做调整。</p>
<p>Ansible的Playbook脚本可以实现自动安装JDK，自动安装Tomcat，自动将应用War包部署到Tomcat下的<code>webapps</code>，<br>修改应用配置文件，启动Tomcat等。而且，这些动作是可以不断重复执行的。</p>
<p>下面是实现上述需求对应的基本概念：  </p>
<ul>
<li><p>模块(module)<br>Ansible使用module来完成任务(task)， 如安装apt，拷贝文件copy，使用模板template等</p>
</li>
<li><p>任务 (task)<br>多个 task 顺序执行，在每个 task 执行结束可以通知 Hanlder 触发新操作。</p>
</li>
<li><p>变量 (Variable)<br>用户定义的变量。</p>
</li>
<li><p>环境 (Facts)<br>Facts 从每台服务器上收集得到，可以用作变量。</p>
</li>
<li><p>主机配置(Inventory)<br>根据场景定义主机列表及分组</p>
</li>
</ul>
<h3 id="Playbooks目录结构"><a href="#Playbooks目录结构" class="headerlink" title="Playbooks目录结构"></a>Playbooks目录结构</h3><p>Ansible通过一组结构化目录及YAML文件描述一个应用的具体部署动作。<br>顶层目录及文件定义主机列表（<code>production/staging</code>），应用部署的流程编排<br>（<code>site.yml/webservers.yml/dbservers.xml</code>），应用执行时的全局变量定义（group_vars/host_vars），<code>roles</code>下定义部署过程中<br>的特定处理单元。下述列举Ansible中Playbook的典型组织结构示例。<br><figure class="highlight plain"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div><div class="line">13</div><div class="line">14</div><div class="line">15</div><div class="line">16</div><div class="line">17</div><div class="line">18</div><div class="line">19</div><div class="line">20</div><div class="line">21</div><div class="line">22</div><div class="line">23</div><div class="line">24</div><div class="line">25</div><div class="line">26</div><div class="line">27</div><div class="line">28</div><div class="line">29</div><div class="line">30</div><div class="line">31</div><div class="line">32</div><div class="line">33</div><div class="line">34</div><div class="line">35</div><div class="line">36</div><div class="line">37</div><div class="line">38</div></pre></td><td class="code"><pre><div class="line">production                # inventory file for production servers</div><div class="line">staging                   # inventory file for staging environment</div><div class="line"></div><div class="line">group_vars/</div><div class="line">   group1                 # here we assign variables to particular groups</div><div class="line">   group2                 # &quot;&quot;</div><div class="line">host_vars/</div><div class="line">   hostname1              # if systems need specific variables, put them here</div><div class="line">   hostname2              # &quot;&quot;</div><div class="line"></div><div class="line">library/                  # if any custom modules, put them here (optional)</div><div class="line">filter_plugins/           # if any custom filter plugins, put them here (optional)</div><div class="line"></div><div class="line">site.yml                  # master playbook</div><div class="line">webservers.yml            # playbook for webserver tier</div><div class="line">dbservers.yml             # playbook for dbserver tier</div><div class="line"></div><div class="line">roles/</div><div class="line">    common/               # this hierarchy represents a &quot;role&quot;</div><div class="line">        tasks/            #</div><div class="line">            main.yml      #  &lt;-- tasks file can include smaller files if warranted</div><div class="line">        handlers/         #</div><div class="line">            main.yml      #  &lt;-- handlers file</div><div class="line">        templates/        #  &lt;-- files for use with the template resource</div><div class="line">            ntp.conf.j2   #  &lt;------- templates end in .j2</div><div class="line">        files/            #</div><div class="line">            bar.txt       #  &lt;-- files for use with the copy resource</div><div class="line">            foo.sh        #  &lt;-- script files for use with the script resource</div><div class="line">        vars/             #</div><div class="line">            main.yml      #  &lt;-- variables associated with this role</div><div class="line">        defaults/         #</div><div class="line">            main.yml      #  &lt;-- default lower priority variables for this role</div><div class="line">        meta/             #</div><div class="line">            main.yml      #  &lt;-- role dependencies</div><div class="line"></div><div class="line">    webtier/              # same kind of structure as &quot;common&quot; was above, done for the webtier role</div><div class="line">    monitoring/           # &quot;&quot;</div><div class="line">    fooapp/               # &quot;&quot;</div></pre></td></tr></table></figure></p>
<h2 id="YAML简介"><a href="#YAML简介" class="headerlink" title="YAML简介"></a>YAML简介</h2><p><a href="http://yaml.org/" target="_blank" rel="external">YAML</a>是JSON的一个变种。下面简要列举YAML的语法</p>
<ul>
<li><p># 注释<br># This is a YAML comment</p>
</li>
<li><p>String（不必加引号）<br><code>this is a lovely sentence</code></p>
</li>
<li><p>Booleans<br><code>Ture</code> <code>False</code> <code>Yes</code> <code>No</code></p>
</li>
<li><p>Lists</p>
<figure class="highlight yaml"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div><div class="line">13</div><div class="line">14</div><div class="line">15</div><div class="line">16</div><div class="line">17</div><div class="line">18</div><div class="line">19</div><div class="line">20</div><div class="line">21</div><div class="line">22</div><div class="line">23</div><div class="line">24</div><div class="line">25</div></pre></td><td class="code"><pre><div class="line"><span class="attr">movies:</span></div><div class="line"><span class="bullet">  -</span> My Fair Lady  </div><div class="line"><span class="bullet">  -</span> Oklahoma  </div><div class="line"><span class="bullet">  -</span> The Pirates of Penzance  </div><div class="line">```  </div><div class="line">  或  </div><div class="line">  `movies: [My Fair Lady, Oklahoma, The Pirates of Penzance]`</div><div class="line"></div><div class="line"><span class="bullet">-</span> 字典  </div><div class="line">```YAML</div><div class="line"><span class="attr">location:</span></div><div class="line"><span class="attr">    address:</span> <span class="number">742</span> Evergreen Terrace  </div><div class="line"><span class="attr">    city:</span> Springfield  </div><div class="line"><span class="attr">    state:</span> North Takoma  </div><div class="line">```  </div><div class="line">  或  </div><div class="line">  `location: &#123;address: <span class="number">742</span> Evergreen Terrace, city: Springfield, state: North Takoma&#125;`</div><div class="line"></div><div class="line"><span class="bullet">-</span> 跨行  </div><div class="line">```YAML</div><div class="line"><span class="attr">  address:</span> <span class="string">&gt;  </span></div><div class="line">        Department of Computer Science,  </div><div class="line">        A.V. Williams Building,  </div><div class="line">        University of Maryland  </div><div class="line"><span class="attr">  city:</span> College Park</div></pre></td></tr></table></figure>
</li>
</ul>
<h2 id="Playbook介绍"><a href="#Playbook介绍" class="headerlink" title="Playbook介绍"></a>Playbook介绍</h2><p>Playbooks由一组Play构成，每个Play由一个yaml文件描述。如下示例：<br><figure class="highlight yaml"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div><div class="line">13</div><div class="line">14</div><div class="line">15</div><div class="line">16</div></pre></td><td class="code"><pre><div class="line"><span class="attr">- name:</span> Configure webserver with nginx</div><div class="line"><span class="attr">  hosts:</span> webservers</div><div class="line"><span class="attr">  sudo:</span> <span class="literal">True</span></div><div class="line"><span class="attr">  tasks:</span></div><div class="line"><span class="attr">    - name:</span> install nginx</div><div class="line"><span class="attr">      apt:</span> name=nginx update_cache=<span class="literal">yes</span></div><div class="line"><span class="attr">    - name:</span> copy nginx config file</div><div class="line"><span class="attr">      copy:</span> src=files/nginx.conf dest=/etc/nginx/sites-available/default</div><div class="line"><span class="attr">    - name:</span> enable configuration</div><div class="line"><span class="attr">      file:</span> <span class="string">&gt;</span></div><div class="line">        dest=/etc/nginx/sites-enabled/default</div><div class="line">        src=/etc/nginx/sites-available/default</div><div class="line">        state=link</div><div class="line"><span class="attr">    - name:</span> copy index.html</div><div class="line"><span class="attr">      template:</span> src=templates/index.html.j2</div><div class="line">               dest=/usr/share/nginx/html/index.html mode=<span class="number">0644</span></div></pre></td></tr></table></figure></p>
<p>构成一个Play的要素包括：  </p>
<ul>
<li>hosts   （必须）  一组待配置的主机</li>
<li>name    （可选）</li>
<li>sudo    （可选）  以root用户运行所有task</li>
<li>vars    （可选）  用于该Play的变量</li>
<li>tasks   （必须）  在主机上执行的一组任务</li>
</ul>
<p>对于复杂的Play定义，tasks被转移到<code>roles</code>下分模块定义，每个role复杂完成一部分部署动作。<br><figure class="highlight yaml"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div></pre></td><td class="code"><pre><div class="line"><span class="attr">- name:</span> Configure webserver with nginx</div><div class="line"><span class="attr">  hosts:</span> webservers</div><div class="line"><span class="attr">  sudo:</span> <span class="literal">True</span></div><div class="line">  roles：</div><div class="line"><span class="bullet">     -</span> jdk</div><div class="line"><span class="bullet">     -</span> tomcat</div><div class="line"><span class="bullet">     -</span> mydemo</div><div class="line"><span class="bullet">-</span> include  monitoring.yml</div></pre></td></tr></table></figure></p>
<h2 id="Playbook的高级特性"><a href="#Playbook的高级特性" class="headerlink" title="Playbook的高级特性"></a>Playbook的高级特性</h2><h3 id="Lookup查找"><a href="#Lookup查找" class="headerlink" title="Lookup查找"></a>Lookup查找</h3><figure class="highlight yaml"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div></pre></td><td class="code"><pre><div class="line"><span class="attr">- name:</span> Add my public key as an EC2 key</div><div class="line"><span class="attr">  ec2_key:</span> <span class="string">&gt;</span></div><div class="line">    name=mykey key_material="<span class="template-variable">&#123;&#123; lookup('file', '/Users/test/.ssh/id_rsa.pub') &#125;&#125;</span>"</div><div class="line"></div><div class="line"><span class="attr">- name:</span> get SHA of most recent commit</div><div class="line"><span class="attr">  debug:</span> msg=<span class="string">"<span class="template-variable">&#123;&#123; lookup('pipe', 'git rev-parse HEAD') &#125;&#125;</span>"</span></div><div class="line"></div><div class="line"><span class="attr">- name:</span> get the current shell</div><div class="line"><span class="attr">  debug:</span> msg=<span class="string">"<span class="template-variable">&#123;&#123; lookup('env', 'SHELL') &#125;&#125;</span>"</span></div><div class="line">......</div></pre></td></tr></table></figure>
<table>
<thead>
<tr>
<th>Name</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr>
<td>file</td>
<td>Contents of a file</td>
</tr>
<tr>
<td>password</td>
<td>Randomly generate a password</td>
</tr>
<tr>
<td>pipe</td>
<td>Output of locally executed command</td>
</tr>
<tr>
<td>env</td>
<td>Environment variable</td>
</tr>
<tr>
<td>template</td>
<td>Jinja2 template after evaluation</td>
</tr>
<tr>
<td>csvfile</td>
<td>Entry in a .csv file</td>
</tr>
<tr>
<td>dnstxt</td>
<td>DNS TXT record</td>
</tr>
<tr>
<td>redis_kv</td>
<td>Redis key lookup</td>
</tr>
<tr>
<td>etcd</td>
<td>etcd key lookup</td>
</tr>
</tbody>
</table>
<h3 id="遍历"><a href="#遍历" class="headerlink" title="遍历"></a>遍历</h3><p>Ansible支持从多种源遍A历获取数据，如列表，文件行，字典等等。<br><figure class="highlight yaml"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div><div class="line">13</div></pre></td><td class="code"><pre><div class="line"><span class="attr">- name:</span> Send out a slack message</div><div class="line"><span class="attr">  slack:</span></div><div class="line"><span class="attr">    domain:</span> example.slack.com</div><div class="line"><span class="attr">    token:</span> <span class="string">"<span class="template-variable">&#123;&#123; slack_token &#125;&#125;</span>"</span></div><div class="line"><span class="attr">    msg:</span> <span class="string">"<span class="template-variable">&#123;&#123; item &#125;&#125;</span> was in the list"</span></div><div class="line"><span class="attr">  with_lines:</span></div><div class="line"><span class="bullet">    -</span> cat files/turing.txt</div><div class="line"></div><div class="line"><span class="attr">- name:</span> add public keys to account</div><div class="line"><span class="attr">  authorized_key:</span> user=deploy key=<span class="string">"<span class="template-variable">&#123;&#123; lookup('file', item) &#125;&#125;</span>"</span></div><div class="line"><span class="attr">  with_fileglob:</span></div><div class="line"><span class="bullet">    -</span> /var/keys/*.pub</div><div class="line"><span class="bullet">    -</span> keys/*.pub</div></pre></td></tr></table></figure></p>
<table>
<thead>
<tr>
<th>Name</th>
<th>Input</th>
<th>Looping strategy</th>
</tr>
</thead>
<tbody>
<tr>
<td>with_items</td>
<td>list</td>
<td>Loop over list elements</td>
</tr>
<tr>
<td>with_lines</td>
<td>command to execute</td>
<td>Loop over lines in command output</td>
</tr>
<tr>
<td>with_fileglob</td>
<td>glob</td>
<td>Loop over filenames</td>
</tr>
<tr>
<td>with_first_found</td>
<td>list of paths</td>
<td>First file in input that exists</td>
</tr>
<tr>
<td>with_dict</td>
<td>dictionary</td>
<td>Loop over dictionary elements</td>
</tr>
<tr>
<td>with_flattened</td>
<td>list of lists</td>
<td>Loop over flattened list</td>
</tr>
<tr>
<td>with_indexed_items</td>
<td>list</td>
<td>Single iteration</td>
</tr>
<tr>
<td>with_nested</td>
<td>list</td>
<td>Nested loop</td>
</tr>
<tr>
<td>with_random_choice</td>
<td>list</td>
<td>Single iteration</td>
</tr>
<tr>
<td>with_sequence</td>
<td>sequence of integers</td>
<td>Loop over sequence</td>
</tr>
<tr>
<td>with_subelements</td>
<td>list of dictionaries</td>
<td>Nested loop</td>
</tr>
<tr>
<td>with_together</td>
<td>list of lists</td>
<td>Loop over zipped list</td>
</tr>
<tr>
<td>with_inventory_hostnames</td>
<td>host pattern</td>
<td>Loop over matching hosts</td>
</tr>
</tbody>
</table>
<h2 id="Ansible调试环境"><a href="#Ansible调试环境" class="headerlink" title="Ansible调试环境"></a>Ansible调试环境</h2><p>请参考<a href="/2015-09-01/autoit-ansible-with-vagrant">采用Vagrant搭建Ansible playbook脚本开发测试环境</a>。</p>
<h2 id="Playbook部署示例"><a href="#Playbook部署示例" class="headerlink" title="Playbook部署示例"></a>Playbook部署示例</h2><p>场景：假设一个系统存在<em>接口</em>和<em>后台</em>两大子系统，接口子系统包含<em>用户服务</em>，<em>产品服务</em>和<em>WEB接口</em>三部分，后台子系统包括<em>管理服务</em>和<br><em>管理WEB UI</em> 两个模块。现在有两台主机111和112，部署要求如下：</p>
<ul>
<li>接口子系统:  <ul>
<li>用户服务<br>111，112  </li>
<li>产品服务<br>111,112  </li>
<li>WEB接口（Tomcat）<br>111,112  </li>
</ul>
</li>
<li>后台子系统：  <ul>
<li>管理服务<br>111<br>-后台WEB UI（Tomcat）<br>112  </li>
</ul>
</li>
</ul>
<p>对应的Playbook结构如下：</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div><div class="line">13</div><div class="line">14</div><div class="line">15</div><div class="line">16</div><div class="line">17</div><div class="line">18</div><div class="line">19</div><div class="line">20</div><div class="line">21</div><div class="line">22</div><div class="line">23</div><div class="line">24</div></pre></td><td class="code"><pre><div class="line">|---test  测试环境机器配置</div><div class="line">|---production  生产环境机器配置</div><div class="line">|---admin.yml  后台子系统部署脚本（聚合）</div><div class="line">|---admin-user-service.yml  用户服务服务部署脚本（聚合）</div><div class="line">|---admin-user-service-deploy.yml  用户服务服务部署脚本</div><div class="line">|---admin-user-service-restart.yml  用户服务服务启动脚本</div><div class="line">|---admin-web.yml  管理WEB UI部署脚本（聚合）</div><div class="line">|---admin-web-deploy.yml  管理WEB UI部署脚本</div><div class="line">|---admin-web-restart.yml  管理WEB UI启动脚本</div><div class="line">|--- 。。。。。</div><div class="line">|---appapi.yml  接口子系统部署脚本（聚合）</div><div class="line">|--- 。。。。。</div><div class="line">|---group_vars</div><div class="line">    |------ all  全局脚本变量配置</div><div class="line">|---roles</div><div class="line">    |------ selinux     与操作系统安全（端口配置）相关的脚本</div><div class="line">    |------ oracle-jdk  安装oracle jdk</div><div class="line">    |------ supervisor  通过supervisor控制tomcat服务</div><div class="line">    |------ tomcat      tomcat服务配置</div><div class="line">    |------ admin_user  后台子系统中管理服务</div><div class="line">    |------ ......</div><div class="line">    |------ adminweb   后台子系统WEB UI</div><div class="line">            |----- ......</div><div class="line">    |------ ......</div></pre></td></tr></table></figure>
<p><strong>提示：</strong> 在实践中，为了最小化持续部署对生产环境offline造成影响，可将部署与服务的停用重启应拆分为两个部分，部署动作先将构件推送到主机并修改<br>生产环境配置，准备就绪后再统一控制各个服务的重启，最小化服务停用时间。</p>
<h2 id="结论"><a href="#结论" class="headerlink" title="结论"></a>结论</h2><ul>
<li>本文概略介绍了自动化部署工具Ansible，通过自动化部署工具，我们可以将研发的产品沿着自动化生产线直接推送给终端用户直接体验，从而<br>最快速度响应用户需求与反馈。</li>
<li>在下一篇文章中，我会将Ansible与之前的<a href="http://github.com/christtrc/greeter-osgi-example" target="_blank" rel="external">greeter-osgi-example</a>示例结合，<br>并在Jenkins中进行任务定义，实现自动化部署。</li>
</ul>

      
    </div>

    <div>
      
        

      
    </div>

    <div>
      
        

      
    </div>


    <footer class="post-footer">
      
        <div class="post-tags">
          
            <a href="/tags/jenkins/" rel="tag"># jenkins</a>
          
            <a href="/tags/ansible/" rel="tag"># ansible</a>
          
            <a href="/tags/playbook/" rel="tag"># playbook</a>
          
        </div>
      

      
        <div class="post-nav">
          <div class="post-nav-next post-nav-item">
            
              <a href="/2015/09/21/snippets-tesseract-ocr/" rel="next" title="Tesseract OCR 安装使用">
                <i class="fa fa-chevron-left"></i> Tesseract OCR 安装使用
              </a>
            
          </div>

          <span class="post-nav-divider"></span>

          <div class="post-nav-prev post-nav-item">
            
              <a href="/2015/09/24/autoit-continuous-deploy/" rel="prev" title="IT自动化(12)——Jenkins+Ansible实现持续部署">
                IT自动化(12)——Jenkins+Ansible实现持续部署 <i class="fa fa-chevron-right"></i>
              </a>
            
          </div>
        </div>
      

      
      
    </footer>
  </article>



    <div class="post-spread">
      
        <div class="ds-share flat" data-thread-key="2015/09/23/autoit-ansible/"
     data-title="IT自动化(11)——持续部署的支撑工具Ansible"
     data-content=""
     data-url="http://chrisrc.me/2015/09/23/autoit-ansible/">
  <div class="ds-share-inline">
    <ul  class="ds-share-icons-16">

      <li data-toggle="ds-share-icons-more"><a class="ds-more" href="javascript:void(0);">分享到：</a></li>
      <li><a class="ds-weibo" href="javascript:void(0);" data-service="weibo">微博</a></li>
      <li><a class="ds-qzone" href="javascript:void(0);" data-service="qzone">QQ空间</a></li>
      <li><a class="ds-qqt" href="javascript:void(0);" data-service="qqt">腾讯微博</a></li>
      <li><a class="ds-wechat" href="javascript:void(0);" data-service="wechat">微信</a></li>

    </ul>
    <div class="ds-share-icons-more">
    </div>
  </div>
</div>
      
    </div>
  </div>


          </div>
          


          
  <div class="comments" id="comments">
    
      <div class="ds-thread" data-thread-key="2015/09/23/autoit-ansible/"
           data-title="IT自动化(11)——持续部署的支撑工具Ansible" data-url="http://chrisrc.me/2015/09/23/autoit-ansible/">
      </div>
    
  </div>


        </div>
        
          
  
  <div class="sidebar-toggle">
    <div class="sidebar-toggle-line-wrap">
      <span class="sidebar-toggle-line sidebar-toggle-line-first"></span>
      <span class="sidebar-toggle-line sidebar-toggle-line-middle"></span>
      <span class="sidebar-toggle-line sidebar-toggle-line-last"></span>
    </div>
  </div>

  <aside id="sidebar" class="sidebar">
    <div class="sidebar-inner">

      

      
        <ul class="sidebar-nav motion-element">
          <li class="sidebar-nav-toc sidebar-nav-active" data-target="post-toc-wrap" >
            文章目录
          </li>
          <li class="sidebar-nav-overview" data-target="site-overview">
            站点概览
          </li>
        </ul>
      

      <section class="site-overview sidebar-panel">
        <div class="site-author motion-element" itemprop="author" itemscope itemtype="http://schema.org/Person">
          <img class="site-author-image" itemprop="image"
               src="/images/avatar.gif"
               alt="chrisrc" />
          <p class="site-author-name" itemprop="name">chrisrc</p>
          <p class="site-description motion-element" itemprop="description"></p>
        </div>
        <nav class="site-state motion-element">
          <div class="site-state-item site-state-posts">
            <a href="/archives">
              <span class="site-state-item-count">69</span>
              <span class="site-state-item-name">日志</span>
            </a>
          </div>

          
            <div class="site-state-item site-state-categories">
              <a href="/categories">
                <span class="site-state-item-count">21</span>
                <span class="site-state-item-name">分类</span>
              </a>
            </div>
          

          
            <div class="site-state-item site-state-tags">
              <a href="/tags">
                <span class="site-state-item-count">162</span>
                <span class="site-state-item-name">标签</span>
              </a>
            </div>
          

        </nav>

        

        <div class="links-of-author motion-element">
          
            
              <span class="links-of-author-item">
                <a href="https://github.com/christtrc" target="_blank" title="GitHub">
                  
                    <i class="fa fa-fw fa-github"></i>
                  
                  GitHub
                </a>
              </span>
            
              <span class="links-of-author-item">
                <a href="https://twitter.com/chrisrc" target="_blank" title="Twitter">
                  
                    <i class="fa fa-fw fa-twitter"></i>
                  
                  Twitter
                </a>
              </span>
            
          
        </div>

        
        
          <div class="cc-license motion-element" itemprop="license">
            <a href="https://creativecommons.org/licenses/by-nc-sa/4.0/" class="cc-opacity" target="_blank">
              <img src="/images/cc-by-nc-sa.svg" alt="Creative Commons" />
            </a>
          </div>
        

        
        

        


      </section>

      
      <!--noindex-->
        <section class="post-toc-wrap motion-element sidebar-panel sidebar-panel-active">
          <div class="post-toc">

            
              
            

            
              <div class="post-toc-content"><ol class="nav"><li class="nav-item nav-level-2"><a class="nav-link" href="#前文回顾"><span class="nav-number">1.</span> <span class="nav-text">前文回顾</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#Ansible简介"><span class="nav-number">2.</span> <span class="nav-text">Ansible简介</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#Ansible的安装"><span class="nav-number">3.</span> <span class="nav-text">Ansible的安装</span></a><ol class="nav-child"><li class="nav-item nav-level-3"><a class="nav-link" href="#依赖"><span class="nav-number">3.1.</span> <span class="nav-text">依赖</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#安装"><span class="nav-number">3.2.</span> <span class="nav-text">安装</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#本机环境的配置"><span class="nav-number">3.3.</span> <span class="nav-text">本机环境的配置</span></a></li></ol></li><li class="nav-item nav-level-2"><a class="nav-link" href="#Ansible常用命令简介"><span class="nav-number">4.</span> <span class="nav-text">Ansible常用命令简介</span></a><ol class="nav-child"><li class="nav-item nav-level-3"><a class="nav-link" href="#ansible-命令"><span class="nav-number">4.1.</span> <span class="nav-text">ansible 命令</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#ansible-doc-命令"><span class="nav-number">4.2.</span> <span class="nav-text">ansible-doc 命令</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#ansible-playbook-命令"><span class="nav-number">4.3.</span> <span class="nav-text">ansible-playbook 命令</span></a></li></ol></li><li class="nav-item nav-level-2"><a class="nav-link" href="#自动化部署工具简单比较"><span class="nav-number">5.</span> <span class="nav-text">自动化部署工具简单比较</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#Ansible的功能"><span class="nav-number">6.</span> <span class="nav-text">Ansible的功能</span></a><ol class="nav-child"><li class="nav-item nav-level-3"><a class="nav-link" href="#工作机制"><span class="nav-number">6.1.</span> <span class="nav-text">工作机制</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#部署中的基本概念"><span class="nav-number">6.2.</span> <span class="nav-text">部署中的基本概念</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#Playbooks目录结构"><span class="nav-number">6.3.</span> <span class="nav-text">Playbooks目录结构</span></a></li></ol></li><li class="nav-item nav-level-2"><a class="nav-link" href="#YAML简介"><span class="nav-number">7.</span> <span class="nav-text">YAML简介</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#Playbook介绍"><span class="nav-number">8.</span> <span class="nav-text">Playbook介绍</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#Playbook的高级特性"><span class="nav-number">9.</span> <span class="nav-text">Playbook的高级特性</span></a><ol class="nav-child"><li class="nav-item nav-level-3"><a class="nav-link" href="#Lookup查找"><span class="nav-number">9.1.</span> <span class="nav-text">Lookup查找</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#遍历"><span class="nav-number">9.2.</span> <span class="nav-text">遍历</span></a></li></ol></li><li class="nav-item nav-level-2"><a class="nav-link" href="#Ansible调试环境"><span class="nav-number">10.</span> <span class="nav-text">Ansible调试环境</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#Playbook部署示例"><span class="nav-number">11.</span> <span class="nav-text">Playbook部署示例</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#结论"><span class="nav-number">12.</span> <span class="nav-text">结论</span></a></li></ol></div>
            

          </div>
        </section>
      <!--/noindex-->
      

    </div>
  </aside>


        
      </div>
    </main>

    <footer id="footer" class="footer">
      <div class="footer-inner">
        <div class="copyright" >
  
  &copy;  2015 - 
  <span itemprop="copyrightYear">2017</span>
  <span class="with-love">
    <i class="fa fa-heart"></i>
  </span>
  <span class="author" itemprop="copyrightHolder">
     
      <a href="mailto:chrisrc@qq.com">chrisrc</a> 
    
  </span>
  <span class="author"> &nbsp; QQ: 58122705 </span>
</div>


<div class="powered-by">
  由 <a class="theme-link" href="https://hexo.io">Hexo</a> 强力驱动
</div>

<div class="theme-info">
  主题 -
  <a class="theme-link" href="https://github.com/iissnan/hexo-theme-next">
    NexT.Mist
  </a>
</div>


        

        
      </div>
    </footer>

    <div class="back-to-top">
      <i class="fa fa-arrow-up"></i>
    </div>
  </div>

  

<script type="text/javascript">
  if (Object.prototype.toString.call(window.Promise) !== '[object Function]') {
    window.Promise = null;
  }
</script>









  



  
  <script type="text/javascript" src="/lib/jquery/index.js?v=2.1.3"></script>

  
  <script type="text/javascript" src="/lib/fastclick/lib/fastclick.min.js?v=1.0.6"></script>

  
  <script type="text/javascript" src="/lib/jquery_lazyload/jquery.lazyload.js?v=1.9.7"></script>

  
  <script type="text/javascript" src="/lib/velocity/velocity.min.js?v=1.2.1"></script>

  
  <script type="text/javascript" src="/lib/velocity/velocity.ui.min.js?v=1.2.1"></script>

  
  <script type="text/javascript" src="/lib/fancybox/source/jquery.fancybox.pack.js?v=2.1.5"></script>


  


  <script type="text/javascript" src="/js/src/utils.js?v=5.1.0"></script>

  <script type="text/javascript" src="/js/src/motion.js?v=5.1.0"></script>



  
  

  
  <script type="text/javascript" src="/js/src/scrollspy.js?v=5.1.0"></script>
<script type="text/javascript" src="/js/src/post-details.js?v=5.1.0"></script>



  


  <script type="text/javascript" src="/js/src/bootstrap.js?v=5.1.0"></script>



  

  
    
  

  <script type="text/javascript">
    var duoshuoQuery = {short_name:"chrisrc"};
    (function() {
      var ds = document.createElement('script');
      ds.type = 'text/javascript';ds.async = true;
      ds.id = 'duoshuo-script';
      ds.src = (document.location.protocol == 'https:' ? 'https:' : 'http:') + '//static.duoshuo.com/embed.js';
      ds.charset = 'UTF-8';
      (document.getElementsByTagName('head')[0]
      || document.getElementsByTagName('body')[0]).appendChild(ds);
    })();
  </script>

  
    
    
    <script src="/lib/ua-parser-js/dist/ua-parser.min.js?v=0.7.9"></script>
    <script src="/js/src/hook-duoshuo.js"></script>
  








  
  

  

  

  
<script>
(function(){
    var bp = document.createElement('script');
    var curProtocol = window.location.protocol.split(':')[0];
    if (curProtocol === 'https') {
        bp.src = 'https://zz.bdstatic.com/linksubmit/push.js';        
    }
    else {
        bp.src = 'http://push.zhanzhang.baidu.com/push.js';
    }
    var s = document.getElementsByTagName("script")[0];
    s.parentNode.insertBefore(bp, s);
})();
</script>


  
<script>
(function(){
   var src = (document.location.protocol == "http:") ? "http://js.passport.qihucdn.com/11.0.1.js?ed903ab05fbc5fa64d95e4bfbf3d3a04":"https://jspassport.ssl.qhimg.com/11.0.1.js?ed903ab05fbc5fa64d95e4bfbf3d3a04";
   document.write('<script src="' + src + '" id="sozz"><\/script>');
})();
</script>

  


</body>
</html>
